"""
класс connSQL - обеспечивает процедуру соединения с сервером
класс fmServer - модальная форма (параметры соединения с сервером)
"""

import os
import sys
import configparser

from PyQt5.QtSql import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *


class ConnSql():
    """
    """
    def __init__(self, ini_file, driver="QMYSQL", conn_name="one"):

        self.driver = driver
        self.conn_name = conn_name

        # ЧТЕНИЕ INI ФАЙЛА
        # Создаем переменную парсера ini файла. Формируем полный путь до ini
        # файла. Читаем ini файл. Отсутствие ini файла или нужной секции
        # равнозначно, поэтому достаточно проверить наличие секции в словаре.
        # Если секции SERVER нет, то добовляем с пустыми значениями.

        self.config = configparser.ConfigParser()
        self.ini_file = "{}\\{}".format(os.getenv('APPDATA'), ini_file)
        self.config.read(self.ini_file)
        if not ('SERVER' in self.config):
            self.config['SERVER'] = {'host_name': '',
                'data_base':'', 'user':'','password':''}

    def connect(self):
        '''
        Открывает БД. Если соединение не удалось, открываем модальную
        форму для настройки соединения с сервером. Если результат работы
        модальной формы положительный, записывает конфиг и возвращает
        указатель на базу данных.
        '''
        db = self.open_db()
        if not db:
            dialog = DialogServer(self.config, self.open_db)
            result = dialog.exec_()
            if result == QDialog.Accepted:
                with open(self.ini_file, 'w') as file_ini:
                    self.config.write(file_ini)
                return dialog.db
            else:
                QSqlDatabase.close()
        else:
            return db


def open_db(config, name):
    '''
    Открывает базу данных, использую параметры из configparser. Если процедура
    успешна, возвражает указатель на базу, иначе выводит сообщение об ошибке.
    '''

    # СОЕДИНЕНИЕ С СЕВЕРОМ
    # Eсли соединение уже активно, вытаскиваем ссылку на соединение, иначе
    # создаём новое соединение.

    if QSqlDatabase.contains(self.conn_name):
        db = QSqlDatabase.database(self.conn_name)
    else:
        db = QSqlDatabase.addDatabase(self.driver, self.conn_name)              #

    # СОЕДИНЕНИЕ С БД
    # Грузим параметры соединения с БД из ConfigParser.
    # создаём новое соединение. Возможные нарушения структуры секции
    # в ini файле устраняется функцией get().

    server = self.config['SERVER']
    db.setHostName(server.get('host_name',''))
    db.setDatabaseName(server.get('data_base',''))
    db.setUserName(server.get('user',''))
    db.setPassword(server.get('password',''))

    if db.open():                                                               # открываем соединение
        return db
    else:
        error = db.lastError()
        num_error = error.number()
        if num_error == 1044:
            message = "Введите правильное имя базы данных или обратитесь к системному администратору."
        elif num_error == 1045:
            message = "Введите правильное имя пользователя и/или пароль или обратитесь к системному администратору."
        elif num_error == 2003:
            message = "Введите правильный IP адрес или название сервера или обратитесь к системному администратору."
        else:
            message = ("Код ошибки сервера: {}. Оригинальное сообщение: {}. Обратитесь к программисту."
                .format(num_error,error.text()))
        dialog = QMessageBox()
        dialog.setIcon(QMessageBox.Critical)                                    # иконка
        # dialog.setIconPixmap(QPixmap('Help.png'))
        dialog.setWindowTitle("ОШИБКА СОЕДИНЕНИЯ С БАЗОЙ ДАННЫХ")
        dialog.setText(message)
        dialog.exec_()




class DialogServer(QDialog):
    """
    """

    def __init__(self, config, open):
        super().__init__()

        self.config = config                                                    # переменная конфигурации
        self.open = open                                                        # функция соединения с базой данных

        # ВИДЖЕТЫ
        # Записываем параметры соединения в виджеты полей.
        # Нарушение структуры секции в ini файле устраняется функцией get().

        server = self.config['SERVER']
        self.edt_host_name = QLineEdit(server.get('host_name',''))
        self.edt_database = QLineEdit(server.get('data_base',''))
        self.edt_user_name = QLineEdit(server.get('user',''))
        self.edt_password = QLineEdit(server.get('password',''))
        self.btn_open_db = QPushButton('ОТКРЫТЬ БАЗУ ДАННЫХ')
        self.btn_open_db.clicked.connect(self.open_db)

        # ФОРМА
        # Добавлем к форме все виджеты.

        self.form = QFormLayout()
        self.form.addRow("Сервер", self.edt_host_name)
        self.form.addRow("База", self.edt_database)
        self.form.addRow("Логин", self.edt_user_name)
        self.form.addRow("Пароль", self.edt_password)
        self.form.addRow(self.btn_open_db)
        self.setLayout(self.form)
        self.setWindowTitle("ПАРАМЕТРЫ БД")
        self.setMinimumWidth(200)


    def open_db(self):
        """
        Проверка заполнения полей. Загрузка значений полей в переменную конфигурации.
        Попытка соединения с сервером. Закрытие формы в случае удачного соединения
        """
        if (not self.edt_host_name.text() or                                    # проверка заполнения полей
            not self.edt_database.text() or
            not self.edt_user_name.text() or
            not self.edt_password.text()):
            dialog = QMessageBox()
            dialog.setIcon(QMessageBox.Warning)                                 # иконка
            dialog.setWindowTitle("НЕДОСТАТОЧНО ИНФОРМАЦИИ")
            dialog.setText("Все поля должны быть заполнены.")
            dialog.exec_()
            return

        server = self.config['SERVER']                                          # берём из конфиг секцию SERVER
        server['host_name'] = self.edt_host_name.text()                         # загрузка полей в
        server['data_base'] = self.edt_database.text()
        server['user'] = self.edt_user_name.text()
        server['password'] = self.edt_password.text()

        self.db = self.open()                                                   # открываем соединение
        if self.db:                                                             #
            self.accept()

    def closeEvent(self,е):
        ignore  ()
        self.ignore()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    D = connSQL("test.ini")
    db = D.connect()
    if db:
        print("OK")
